package item49;

import item21.Comparator;

/**
 * 第49条：基本类型优先于装箱基本类型
 */
public class Main01 {

    static Integer i;

    public static void main(String[] args) {

        // 基本类型与装箱基本类型三个主要区别
        // 1.基本类型只有值，而装箱基本类型则具有与它们的值不同的同一性。
        // 两个装箱基本类型可以具有相同的值 和不同的同一性。
        // 2.基本类型只有功能完备的值，而每个装箱基本类型除了它对应基本类型的所有功能值之外，还有个非功能值:null.
        // 3.基本类型通常比装箱基本类型更节省时间和空间。

        // Broken comparator - can you spot the flaw?
        // 破损的比较器 - 你能发现缺陷吗？
        Comparator<Integer> naturalOrder = new Comparator<Integer>() {
            @Override
            public int compare(Integer t1, Integer t2) {
                return t1 < t2 ? -1 : (t1 == t2 ? 0 : 1);
            }
        };

        // 对装箱基本类型运用==操作符几乎总是错误的。
        System.out.println(naturalOrder.compare(new Integer(42), new Integer(42)));

        Comparator<Integer> naturalOrder2 = new Comparator<Integer>() {
            @Override
            public int compare(Integer t1, Integer t2) {
                int f = t1; // auto-unboxing
                int s = t2; // auto-unboxing
                return f < s ? -1 : (f == s ? 0 : 1); // No nuboxing
            }
        };

        System.out.println(naturalOrder2.compare(new Integer(42), new Integer(42)));

        // 当在一项操作中混合使用基本类型和装箱基本类型时，装箱基本类型就会自动拆箱。
//        if (i == 42) //Integer 与 int 进行比较，Integer自动拆箱，Null对象自动拆箱会得到一个nullPointerException异常。
//            System.out.println("Unbelievable");

        // hideously slow program! Can you spot the object creation?
        // 可怕的慢程序！你能找出哪里创建对象吗？
        Long sum = 0L;
        for (long i = 0; i < Integer.MAX_VALUE; i++) {
            sum += i; // sum一直再创建
        }
        System.out.println(sum);

        // 什么时候使用装箱基本类型？
        // 1. 作为集合中的元素、键和值。你不能将基本类型放在集合中，因此必须使用装箱基本类型。
        // 2. 在参数化类型中，必须使用装箱基本类型作为类型参数，因为java不允许使用基本类型。
        // 例如，你不能将变量声明为ThreadLocal<int>类型，因此必须使用ThreadLocal<Integer>代替。
        // 3. 在进行反射的方法调用时，必须使用装箱基本类型。

        // 自动装箱减少了使用装箱基本类型的繁琐性，但是并没有减少它的风险。


    }

}
